package com.derbysoft.defender.api.requester;

import com.derbysoft.defender.api.ApiRequestException;
import com.derbysoft.defender.util.JsonUtil;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

/**
 * <p>some description here.</p>
 * Created by Afee Lee on 2017-03-20 22:34
 *
 * @author Afee Lee
 * @version 1.0
 * @see Object
 * @since 1.8
 */
public abstract class AbstractRequester implements Requester {

    protected <T> T getForEntity(String url, MultiValueMap<String, String> headers, Class<T> responseType, Object... urlVariables)
            throws ApiRequestException {
        ResponseEntity<String> entity = new RestTemplate().exchange(url, HttpMethod.GET, new HttpEntity<>(null, headers), String.class, urlVariables);
        return execute(responseType, entity);
    }

    protected <T> T postForEntity(String url, Object body, MultiValueMap<String, String> headers, Class<T> responseType, Object... urlVariables)
            throws ApiRequestException {
        ResponseEntity<String> entity = new RestTemplate().exchange(url, HttpMethod.POST, new HttpEntity<>(body, headers), String.class, urlVariables);
        return execute(responseType, entity);
    }

    protected <T> T execute(Class<T> responseType, ResponseEntity<String> entity) {
        HttpStatus httpStatus = entity.getStatusCode();
        Map<String, String> httpHeaders = entity.getHeaders().toSingleValueMap();

        if (!HttpStatus.OK.equals(httpStatus)) {
            //http error
            throw new ApiRequestException(httpStatus.getReasonPhrase())
                    .statusCode(httpStatus.value())
                    .httpHeaders(httpHeaders);
        }

        if (!entity.hasBody()) {
            //success and no response data
            return null;
        }

        String body = entity.getBody();
        if (String.class.equals(responseType)) {
            return (T) body;
        }

        //success and has response data
        return JsonUtil.fromJson(body, responseType);
    }
}
